function [prt, prts, TR] = spmmat2prt(spmmat, prtfile)
% spmmat2prt  - convert a SPM.mat file into BV's PRT file(s)
%
% FORMAT:       [prt, prts, TR] = spmmat2prt(spmmat, prtfile)
%
% Input fields:
%
%       spmmat      either SPM.mat filename or struct with fields
%        .SPM       1x1 struct containing loaded struct
%             - or -
%        .xBF.UNITS units for timing information
%        .xBF.T     number of time bins (also to calc TR)
%        .xBF.dt    delta time for time bins (event-related designs)
%        .Sess      sessions
%          .U       predictors
%            .name  predictor name
%            .ons   onsets
%            .dur   durations
%            .P     parameters (not yet supported by BV)
%
% Output fields:
%
%       prt         object of first session
%       prts        cell array with other session objects
%       TR          TR (useful for further scripting)

% Version:  v0.7a
% Build:    7082721
% Date:     Aug-27 2007, 9:44 PM CEST
% Author:   Jochen Weber, Brain Innovation, B.V., Maastricht, NL
% URL/Info: http://wiki.brainvoyager.com/BVQXtools

% argument check
if nargin < 2 || ...
   (~ischar(spmmat) && ...
    ~isstruct(spmmat)) || ...
    isempty(spmmat) || ...
   ~ischar(prtfile) || ...
    isempty(prtfile)
    error( ...
        'BVQXtools:BadArgument', ...
        'Missing or bad argument. Try ''help %s''.', ...
        mfilename ...
    );
end

% what is spmmat
if ischar(spmmat)
    try
        spmmat = load(spmmat(:)');
        spmmat.SPM;
    catch
        error( ...
            'BVQXtools:BadArgument', ...
            'Invalid SPM.mat filename given.' ...
        );
    end
end
if numel(spmmat) ~= 1
    error( ...
        'BVQXtools:BadArgument', ...
        'Bad dim/size of spmmat argument.' ...
    );
end
if isfield(spmmat, 'SPM')
    spmmat = spmmat.SPM;
end
if numel(spmmat) ~= 1 || ...
   ~isfield(spmmat, 'Sess') || ...
   ~isstruct(spmmat.Sess) || ...
    isempty(spmmat.Sess) || ...
   ~isfield(spmmat.Sess, 'U') || ...
   ~isfield(spmmat, 'xBF') || ...
   ~isstruct(spmmat.xBF) || ...
    isempty(spmmat.xBF) || ...
   ~isfield(spmmat.xBF, 'UNITS') || ...
   ~isfield(spmmat.xBF, 'T') || ...
   ~isfield(spmmat.xBF, 'dt')
    error( ...
        'BVQXtools:BadArgument', ...
        'Invalid SPM.mat structure given.' ...
    );
end

% get some settings
bf_t  = spmmat.xBF.T;
bf_dt = spmmat.xBF.dt;
bf_u  = lower(spmmat.xBF.UNITS);
if ~any(strcmp(bf_u(:)', {'scan', 'scans', 'sec', 'secs'}))
    error( ...
        'BVQXtools:BadArgument', ...
        'Invalid units found in SPM.mat: %s.', ...
        bf_u(:)' ...
    );
end
TR = bf_t * bf_dt;
sess = spmmat.Sess;
switch (bf_u(:)')
    case {'scan', 'scans'}
        ResolutionOfTime = 'Volumes';
        fac = 1;
    case {'sec', 'secs'}
        ResolutionOfTime = 'msec';
        fac = 1000;
end
sessno = numel(sess);
[prtabs{1:2}] = isabsolute(prtfile(:)');
[prtp{1:3}] = fileparts(prtabs{2});
if isempty(prtp{1})
    prtp{1} = '.';
end

% generate protocols
prts = cell(1, sessno);
for sc = 1:sessno
    newprt = bless(BVQXfile('new:prt'), 1);
    newprt.ResolutionOfTime = ResolutionOfTime;
    U = sess(sc).U;
    for uc = 1:numel(U)
        uname = U(uc).name;
        if iscell(uname)
            uname = uname{1};
        end
        uons = U(uc).ons;
        udur = U(uc).dur;
        uevt = (udur == 0);
        onoff = zeros(numel(uons), 2);
        
        % volume based
        if fac == 1
            
            % BVQX is one-based on volumes
            onoff(:, 1) = uons(:) + 1;
            udur(uevt) = 1;
            onoff(:, 2) = onoff(:, 1) + udur(:) - 1;
            
        % msec based
        else
            
            onoff(:, 1) = uons(:);
            udur(uevt) = bf_dt * fac;
            onoff(:, 2) = onoff(:, 1) + udur(:) - 1;
        end
        newprt.AddCond(uname, onoff);
    end
    try
        if sessno > 1
            newprt.Experiment = sprintf('%s - Run %d', prtp{2}, sc);
            newprt.SaveAs(sprintf('%s/%s-run%d.prt', prtp{1}, prtp{2}, sc));
        else
            newprt.Experiment = prtp{2};
            newprt.SaveAs(prtfile(:)');
        end
    catch
        newprt.ClearObject;
        clearbvqxobjects(prts);
        error( ...
            'BVQXtools:BVQXfileError', ...
            'Error saving PRT to file: ''%s''.', ...
            lasterr ...
        );
    end
    
    % only if requested
    if nargout > 1 || ...
        sc == 1
        prts{sc} = newprt;
    else
        newprt.ClearObject;
    end
end

% return first session as prt
prt = prts{1};

% for no output
if nargout < 1
    prt.ClearObject;
end
